%pylab inline
import ShapelyChipDesigns as SD
from shapely.affinity import translate, rotate, scale
from shapely.geometry import LineString, Polygon, Point
from collections import OrderedDict
from collections import Counter
import os
from fitlib import *
#css_styling()
maskname = 'M35 '
name = SD.NotebookName().replace('.ipynb','')
print 'Name=', name
chipheight = 2000
chipwidth = 7000
#RWC, RWG = 10, 4.5 # Lars' thesis
RWC, RWG = 5, 2.25
epsilon = 5.67 # Sonnet simulation
c0 = 299792458
um = 1e-6
GHz = 1e9
N = 12 # number of resonators
chipwidth, chipheight = 7000, 4000
class ListTable(list):
""" Overridden list class which takes a 2-dimensional list of
the form [[1,2,3],[4,5,6]], and renders an HTML Table in
IPython Notebook. """
def _repr_html_(self):
html = ["<table>"]
for row in self:
html.append("<tr>")
for col in row:
html.append("<td>{0}</td>".format(col))
html.append("</tr>")
html.append("</table>")
return ''.join(html)
def make_table(column1,*kwargs):
table = ListTable()
f0 = column1
for i,f in enumerate(f0):
tba = [x[i] for x in kwargs]
table.append([f0[i]]+tba)
return table
# To join all parts together, pass the list of parts.
# If an anker name is the same the two parts will be joined.
# Copies will be made if needed.
# For debug the list of passed parts together with their anker points
# is shown.
class all_parts:
def __init__(self):
self.D = OrderedDict({})
self.I = OrderedDict({})
self.joined = OrderedDict({})
def add_part(self, name):
self.D[name] = eval(name)
def get_part_table(self):
parts = self.D.keys()
ankers = [getattr(part, 'ANKERS').keys()
for part in self.D.values()]
t = make_table(parts,
ankers)
return t
def join_parts(self, name1, name2, anker12=None):
''' the name2 part will be translated to the position of the
name1 part.
anker12 = [name of anker1, name of anker2]'''
part1 = eval(name1)
part2 = eval(name2)
# check if parts are in part-list
for name in [name1, name2]:
if name in self.D.keys():
pass
else:
self.add_part(name)
# if no anker names are given, they are joined on
# identical anker names >> check for identical names
if anker12:
if anker12[0] in getattr(part1, 'ANKERS').keys():
AP1 = getattr(part1, 'ANKERS')[anker12[0]]
else:
print "anker12[0] not in getattr(part1, 'ANKERS').keys()"
if anker12[1] in getattr(part2, 'ANKERS').keys():
AP2 = getattr(part2, 'ANKERS')[anker12[1]]
else:
print "anker12[1] not in getattr(part2, 'ANKERS').keys()"
self.joined[name1+', '+name2] = anker12
else:
sameanker = list((Counter(getattr(part1, 'ANKERS').keys()) & \
Counter(getattr(part2, 'ANKERS').keys())))
if len(sameanker) > 1:
print 'There is more than one anker with the same name!'
else:
AP1 = sameanker[0]
AP2 = sameanker[0]
self.joined[name1+', '+name2] = 'same name: '+sameanker[0]
part2.translate(AP1, AP2)
def update_joined_parts(self):
''' update all joined parts to new locations '''
for i, k in enumerate(self.joined.keys()):
k1, k2 = self.joined.keys()[i].split(', ')
V = self.joined[self.joined.keys()[i]]
#print k1, k2, V
self.join_parts(k1, k2, V)
def get_joined_table(self):
t = make_table(self.joined.keys(),
self.joined.values())
return t
def add_info(self, partname, info):
if partname in self.I.keys():
self.I[partname] += '<br>'+info
else:
self.I[partname] = info
def get_info_table(self):
t = make_table(self.I.keys(),
self.I.values())
return t
def get_closest_point(P, line):
x, y = line.coords.xy
d = [0]*len(x)
for i in arange(len(x)):
Pline = Point(x[i],y[i])
d[i] = P.distance(Pline)
return argmin(d)
def shorten_line(line, shorten_by_length):
''' returns the x, y coordinates of a shortened line '''
print line.length - shorten_by_length
P = line.interpolate(line.length - shorten_by_length)
ind = get_closest_point(P, line)
px, py = line.coords.xy
pxnew = list(px[0:ind]) + [P.x]
pynew = list(py[0:ind]) + [P.y]
return pxnew, pynew
P = all_parts()
P.add_info(r'Mask', maskname)
P.add_info(r'Mask', 'sample type: '+name)
P.add_info(r'Mask', 'path: '+os.getcwd())
P.add_info(r'Sample', r'sample widths:'+str(chipwidth)+r' $\mu$m')
P.add_info(r'Sample', r'sample height:'+str(chipheight)+r' $\mu$m')
P.add_info(r'Resonators', r'$N_{\rm resonators} = $'+str(N))
P.add_info(r'Parameters', r'$\epsilon=$'+str(epsilon))
P.add_info(r'Resonators', r'center widths:'+str(RWC)+r' $\mu$m')
P.add_info(r'Resonators', r'gap widths:'+str(RWG)+r' $\mu$m')
ldes = 4770
def hanging_resonator(desired_length, laddstraight = 0):
global tmonl, tmonx, tmony
ldes = desired_length
X = []
Y = []
# straight first
l1 = 300
P.add_info('Resonators', r'coupler length: '+str(l1)+r' $\mu$m')
X += [0,l1]
Y += [0,0]
# bow down
R = 50
phi = radians(linspace(90,0))
l1d = SD.LineString(zip(R*cos(phi),R*sin(phi)))
p1 = l1d.interpolate(0)
p2 = Point([X[-1], Y[-1]])
l1d = translate(l1d, xoff=p2.x-p1.x, yoff=p2.y-p1.y)
X += l1d.xy[0]
Y += l1d.xy[1]
# bow tmon1
R = 50
yoffadd = 1100 + laddstraight
phi = radians(linspace(180,270))
l1d = SD.LineString(zip(R*cos(phi),R*sin(phi)))
p1 = l1d.interpolate(0)
p2 = Point([X[-1], Y[-1]])
l1d = translate(l1d, xoff=p2.x-p1.x, yoff=p2.y-p1.y-yoffadd)
X += l1d.xy[0]
Y += l1d.xy[1]
# straight tmon2
length = 300
l1d = SD.LineString(zip([0,length],[0,0]))
p1 = l1d.interpolate(0)
p2 = Point([X[-1], Y[-1]])
l1d = translate(l1d, xoff=p2.x-p1.x, yoff=p2.y-p1.y)
resint = SD.LineString(zip(X,Y))
tmonl = resint.length + l1d.length/2.
X += l1d.xy[0]
Y += l1d.xy[1]
tmonx, tmony = l1d.interpolate(l1d.length/2.).xy
# bow tmon2
R = 50
phi = radians(linspace(270,360))
l1d = SD.LineString(zip(R*cos(phi),R*sin(phi)))
p1 = l1d.interpolate(0)
p2 = Point([X[-1], Y[-1]])
l1d = translate(l1d, xoff=p2.x-p1.x, yoff=p2.y-p1.y)
X += l1d.xy[0]
Y += l1d.xy[1]
# curl up wiggle
R = 50
phi = radians(linspace(0, 90))
l1d = SD.LineString(zip(R*cos(phi),R*sin(phi)))
p1 = l1d.interpolate(0)
p2 = Point([X[-1], Y[-1]])
l1d = translate(l1d, xoff=p2.x-p1.x, yoff=p2.y-p1.y)
X += l1d.xy[0]
Y += l1d.xy[1]
# wiggled part
r = 50
off_left = 200
off_right = 20
yend = -350
lc = SD.LineString(zip([X[-1], X[-1]],[Y[-1], yend]))
x0, y0 = lc.xy[0], lc.xy[1]
y1 = linspace(y0[0], y0[1], 20)
x1 = -off_left*sin((y1-min(y1))*pi*1/abs(y0[0]-y0[1]))+x0[0]
l1 = translate(lc,xoff=-off_left)
#l1 = SD.LineString(zip(x1,y1))
x, y = l1.xy[0], l1.xy[1]
l2 = translate(lc,xoff=off_right)
wx, wy = SD.wiggled_function(lc,l1,l2,r,r)
l1d = SD.LineString(zip(wx,wy))
l1d = translate(l1d, xoff=-r, yoff=r)
X += wx[:-2]
Y += wy[:-2]
# curl down wiggle
R = 50
xoffadd = 0# 200
#phi = radians(linspace(270,180))
phi = radians(linspace(270, 360))
l1d = SD.LineString(zip(R*cos(phi),R*sin(phi)))
p1 = l1d.interpolate(0)
p2 = Point([X[-1], Y[-1]])
l1d = translate(l1d, xoff=p2.x-p1.x-xoffadd, yoff=p2.y-p1.y)
X += l1d.xy[0]
Y += l1d.xy[1]
# length of the straight end
res = SD.LineString(zip(X,Y))
dl = ldes - res.length
print dl
# straight end
R = 50
yoffadd = dl
l1d = SD.LineString(zip([0,0],[0,dl]))
p1 = l1d.interpolate(0)
p2 = Point([X[-1], Y[-1]])
l1d = translate(l1d, xoff=p2.x-p1.x, yoff=p2.y-p1.y)
X += l1d.xy[0]
Y += l1d.xy[1]
return X, Y
X, Y = hanging_resonator(ldes)
res = SD.LineString(zip(X,Y))
print res.length, tmonl
endcap = SD.mybox((-RWG,-(RWG*2+RWC)/2.), RWG, RWG*2+RWC)
OUTER = SD.unary_union([endcap, res.buffer((RWC+2*RWG)/2., cap_style=2)])
SD.showPolygons([OUTER])
SD.mouseshow()
#P.add_info('res', r'$l_{\rm res} [\mu m] = $'+str(res.length))
#P.add_info('res', r'$f_{\rm res} [GHz] = \frac{c_0}{4 \times l_{\rm res} \sqrt{\epsilon}}=$'+\
# str(c0/(4*(res.length)*um*sqrt(epsilon))/GHz))
TL = SD.BRAND_NEW_STRUCTURE(OUTER, #res.buffer(2*RWG+RWC, cap_style=2),
res.buffer(RWC/2., cap_style=2))
#TL = SD.MakeTransmissionLine(res.xy[0], res.xy[1], RWC, RWG)
TL.add_anker([tmonx[0], tmony[0]], 'RES_TMON2')
tp = tmonl/res.length
#P.add_info('res-tmon', 'TMON2 location at '+str(round(tp,2))+r'$\times l_{\rm res}$')
xa, ya = res.interpolate(0).xy
TL.add_anker([xa[0], ya[0]], 'L')
xa, ya = res.interpolate(res.length).xy
TL.add_anker([xa[0], ya[0]], 'R')
TL.show_info()
grid()
SD.mouseshow()
TLup = TL.make_copy()
TLup.scale(1,-1, [0,0])
TLup.show_info()
dl = 30
P.add_info('Resonators', r'$\Delta l=$'+str(dl)+r'$\mu$m')
RES = []
for i in arange(N):
x, y = shorten_line(res, i*dl)
resnew = SD.LineString(zip(x, y))
P.add_info('Resonator '+str(i),
r'$l_{\rm res} [\mu m] = $'+str(round(resnew.length,0)))
P.add_info('Resonator '+str(i),
r'$f_{\rm res} [GHz] = \frac{c_0}{4 \times l_{\rm res} \sqrt{\epsilon}}=$'+\
str(round(c0/(4*(resnew.length)*um*sqrt(epsilon))/GHz,2)))
endcap = SD.mybox((-RWG,-(RWG*2+RWC)/2.), RWG, RWG*2+RWC)
OUTER = SD.unary_union([endcap, resnew.buffer((RWC+2*RWG)/2., cap_style=2)])
#TL = SD.BRAND_NEW_STRUCTURE(res.buffer(2*RWG+RWC, cap_style=2),
# OUTER)
TL = SD.BRAND_NEW_STRUCTURE(OUTER, #res.buffer(2*RWG+RWC, cap_style=2),
resnew.buffer(RWC/2., cap_style=2))
#TL = SD.MakeTransmissionLine(resnew.xy[0], resnew.xy[1], RWC, RWG)
TL.add_anker([tmonx[0], tmony[0]], 'RES_TMON2')
tp = tmonl/resnew.length
P.add_info('Resonator '+str(i), r'Transmon at $x=$'+str(round(tp,2))+r'$\times l_{\rm res}$')
P.add_info('Resonator '+str(i), 'corresponding to '+str(round(cos(pi/2.*tp),2))+r' % of $V_m$ ($V(x) = V_m\cos(\pi x/(2 l))$)')
# http://web.physics.ucsb.edu/~bmazin/Papers/2008/Gao/Caltech%20Thesis%202008%20Gao.pdf
xa, ya = resnew.interpolate(0).xy
TL.add_anker([xa[0], ya[0]], 'L')
xa, ya = resnew.interpolate(res.length).xy
TL.add_anker([xa[0], ya[0]], 'R')
if i%2:
RES += [TL]
P.add_info('Resonator '+str(i), 'orientation: down')
else:
TLup = TL.make_copy()
TLup.scale(1,-1, [0,0])
RES += [TLup]
P.add_info('Resonator '+str(i), 'orientation: up')
P.get_info_table()
tllength = 6000
Tline = SD.MakeTransmissionLine([0, tllength], [0,0], RWC, RWG)
hangeroff = -(2*RWG+RWC+2)
xankers = linspace(tllength/(N+1),tllength-tllength/(N+1), N)
P.add_info('Resonators',
'Spacing from arm-coupler to arm-coupler '+str(round(xankers[1]-xankers[0],0))+r'$\mu$m')
yankers = [hangeroff for i in arange(N)]
SD.showPolygons(Tline.get_polygons())
iA, iB = 0, 0
for i in arange(len(xankers)):
if i%2:
Tline.add_anker([xankers[i], yankers[i]], 'A'+str(iA))
plot(xankers[i], yankers[i], 'o')
iA += 1
else:
Tline.add_anker([xankers[i], -1*yankers[i]], 'B'+str(iB))
plot(xankers[i], -1*yankers[i], 'o')
iB += 1
grid()
SD.mouseshow()
print hangeroff
Tline.ANKERS
iA, iB = 0, 0
for i in arange(N):
if i%2:
ankername = 'A'+str(int(iA))
iA += 1
else:
ankername = 'B'+str(int(iB))
iB += 1
print ankername
P.join_parts('Tline', 'RES['+str(int(i))+']', [ankername, 'L'])
Tline.translate([4000,3000], [0,0])
P.update_joined_parts()
for S in P.D.values()[::-1]:
SD.showPolygons(S.get_polygons())
x0, y0 = RES[0].ANKERS['L']
GP = SD.GROUNDPLANE(chipwidth,
chipheight,
0, 0)
GP.add_anker([(chipwidth-tllength)/2., chipheight/2.], 'Tline')
P.join_parts('GP', 'Tline', ['Tline', 0])
P.update_joined_parts()
GP.add_shapes([Tline])
GP.add_shapes(RES)
GP.show_info()
SD.mouseshow()
x0, y0 = RES[0].ANKERS['L']
GPsmall = SD.GROUNDPLANE(chipwidth,
chipheight,
0, 0)
GPsmall.add_anker([(chipwidth-tllength)/2., chipheight/2.], 'Tline')
GPsmall.add_shapes([Tline])
GPsmall.add_shapes([RES[0]])
SD.showPolygons(GPsmall.get_polygons())
SD.savedxf_polylist(GPsmall.get_polygons(), 'GPsmall')
GPs = SD.load_dxf('GPsmall.dxf')
# export one of the hangers:
x0, y0 = RES[0].ANKERS['L']
ew, eh = 800, 400
x0, y0 = x0+150-ew/2., y0-eh/2.
BBOX = SD.mybox((x0,y0), ew, eh)
SD.showPolygons(GPs)
SD.showPolygons([BBOX],['yellow'])
SD.mouseshow()
PS = GPs #GPsmall.get_polygons()
LA = []
for ps in PS:
la = BBOX.intersection(ps)
LA += [la]
LA = SD.flattenMultipolyG(LA)
SD.showPolygons(LA)
grid()
axis('scaled')
SD.mouseshow()
SD.savedxf_polylist(LA, name+'_part00')
SD.convert(name+'_part00.dxf', name+'_part00_rep.dxf')
P.get_info_table()
CX, CY = SD.wiggled_line(l,r,n,p)
T = SD.MakeTransmissionLine(CX,CY, WIR, 0.0)
B = SD.mybox([0,0], IRW, IRH)
xb, yb = B.centroid.xy
BB = SD.mybox([0,0],BW,BH)
print BH
BB = translate(BB,xoff=0.5*(IRW-BW), yoff=0.5*(IRH-BH))
x,y = T.get_polygons('STRUCTURE')[0].centroid.xy
T.translate([xb[0], yb[0]], [x[0],y[0]])
T.show_info()
plot(x[0],y[0],'o')
##### Parameters ########
l = 100 # wiggle height
r = 16 # wiggle radius
n = 11 # number of wiggles
p = 10 # resolution
WIR = 19 # island-reservoir space between the fingers
W = 10 # gap width
IRH = 130 # island + reservoir height
IRW = 325 # island + reservoir width
BH = IRH+2*W # black box height
BW = IRW+2*W # black box width
########### Make the Transmon qubit ########
CX, CY = SD.wiggled_line(l,r,n,p)
T = SD.MakeTransmissionLine(CX,CY, WIR, 0.0)
B = SD.mybox([0,0], IRW, IRH)
BB = SD.mybox([0,0],BW,BH)
BB = translate(BB,xoff=0.5*(IRW-BW), yoff=0.5*(IRH-BH))
cx, cy = SD.anker(T.get_polygons('BOUNDARY')[0],'center')
T.translate(SD.anker(B, 'center'),[cx,cy])
SD.showPolygons([BB,B])
SD.showPolygons(T.get_polygons())
x,y = SD.anker(T.get_polygons('BOUNDARY')[0],'center')
#x,y = T.get_ankerpoint('center')
plot(x,y,'o')
grid()
SD.mouseshow()
##### Parameters ########
########### Make the Transmon qubit ########
TBOUNDS = T.get_polygons('BOUNDARY')
ISLAND,RESERVOIR= B.difference(TBOUNDS[0])
TMON = SD.BRAND_NEW_STRUCTURE(BB,[])
TMON.EBL.add_polis([RESERVOIR,ISLAND])
########### Ankers ############
P = TMON.BOUNDARY.POLIS
x,y = P[0].boundary.xy
inds = SD.find_vertex('top', x,y)
ytop = [y[i] for i in inds[0]]
ytop = mean(ytop)
xtop = [x[i] for i in inds[0]]
xtop = mean(xtop)
TMON.add_anker([xtop, ytop],
'Flux Line')
P = TMON.BOUNDARY.POLIS
x, y = P[0].centroid.xy
TMON.add_anker([x[0],y[0]],
'EBL markers')
xl, yl = SD.anker(TMON.BOUNDARY.POLIS[0],'lower_left')
TMON.add_anker([xl,yl],
'Resonator LL')
xl, yl = SD.anker(TMON.BOUNDARY.POLIS[0],'lower_right')
TMON.add_anker([xl,yl],
'Resonator LR')
########## Plot ##############
SD.showPolygons(TMON.get_polygons()+TMON.get_polygons('EBL'))
for k in TMON.ANKERS.keys():
x,y = TMON.ANKERS[k]
plot(x,y,'o', markersize=5, label=str(k))
legend()
tight_layout()
grid()
SD.mouseshow()
##########################
# larger EBL markers:
mwidth1 = 10
mlength1 = 30
markerlength, markerwidth = mlength1, mwidth1
P0 = LineString([(-0.5,0),(0.5,0)])
M0 = scale(P0, markerlength)
M1 = rotate(M0,90)
M00 = M0.buffer(markerwidth/2., cap_style=3)
M11 = M1.buffer(markerwidth/2., cap_style=3)
MEBL1 = M00.union(M11)
subplot(131)
SD.showPolygons([MEBL1])
##########################
# smaller EBL markers:
mwidth2 = 2
mlength2 = 12
markerlength, markerwidth = mlength2, mwidth2
P0 = LineString([(-0.5,0),(0.5,0)])
M0 = scale(P0, markerlength)
M1 = rotate(M0,90)
M00 = M0.buffer(markerwidth/2., cap_style=3)
M11 = M1.buffer(markerwidth/2., cap_style=3)
MEBL2 = M00.union(M11)
subplot(132)
SD.showPolygons([MEBL2])
# marker positions
wfsize = 500
ps1 = SD.get_RegPoly_xy((0,0), wfsize-2*mlength1, 3)
ps2 = SD.get_RegPoly_xy((0,0), wfsize-2*mlength1-5*mlength2, 3)
subplot(133)
plot(ps1[0], ps1[1])
plot(ps2[0], ps2[1])
tight_layout()
from shapely.geometry import Polygon
RWClarge = 150. # launcher conductor width
RWGlarge = RWG/RWC*RWClarge#67.5 # gap: launcher - groundplane
length = 250 # length of the launcher
length2 = 250 # length of the starter
shuntwidth = 10 # width of the little square on the left side of the starter
##### STRAIGHT STARTER #####
STARTER = SD.MakeTransmissionLine([-length2,0], [0,0],
RWClarge, RWGlarge)
i, o = SD.get_launcher_xy(RWC, RWG, RWClarge, RWGlarge, length)
#plot(i[:,0], i[:,1],'o')
#plot(o[:,0], o[:,1],'o')
LAI = Polygon(i)
LAO = Polygon(o)
LAO
STARTER.get_polygons('STRUCTURE')
##### SHUNT ################
GPLANESHUNT = SD.mybox((-length2, -RWClarge/2.), shuntwidth, RWClarge)
##### MAKE THE LAUNCHER ####
S = STARTER.get_polygons('STRUCTURE')[0]
LAUNCHER_HR = SD.BRAND_NEW_STRUCTURE([LAO]+STARTER.get_polygons('BOUNDARY'),
[LAI]+[S.difference(GPLANESHUNT)])
##### ANKERS ###############
ax, ay = -length2, 0
LAUNCHER_HR.add_anker([ax,ay],'G')
LAUNCHER_HR.add_anker([length,0], 'to Tline')
LAUNCHER_VU = LAUNCHER_HR.make_copy()
LAUNCHER_VU.rotate(90, [ax,ay])
LAUNCHER_HL = LAUNCHER_HR.make_copy()
LAUNCHER_HL.rotate(180, [ax,ay])
LAUNCHER_VD = LAUNCHER_HR.make_copy()
LAUNCHER_VD.rotate(270, [ax,ay])
######## Plot ##############
subplot(121)
axis('equal')
grid()
LAUNCHER_HR.show_info()
###
subplot(122)
LAUNCHER_VD.show_info()
axis('equal')
grid()
SD.mouseshow()